package com.aikg.kgrag_java.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse;
import com.aikg.kgrag_java.mapper.KnowledgedbMapper;
import com.aikg.kgrag_java.pojo.entity.FileStorage;
import com.aikg.kgrag_java.pojo.entity.IndexDocument;
import com.aikg.kgrag_java.pojo.entity.Knowledgedb;
import com.aikg.kgrag_java.service.KnowledgeDBService;
import com.aikg.kgrag_java.utils.ChineseSentenceSplitter;
import com.aikg.kgrag_java.utils.MinioUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

@Service
public class KnowledgeDBServiceImpl extends ServiceImpl<KnowledgedbMapper, Knowledgedb>
        implements KnowledgeDBService {

    @Resource
    private MinioUtil minioUtil;

    @Resource
    private IndexServiceImpl indexService;

    @Resource
    private FileStorageServiceImpl fileStorageService;

    @Resource
    private ElasticsearchClient elasticsearchClient;

    @Resource
    private EmbeddingServiceImpl embeddingService;

    /**
     * 在mysql建立知识库
     * @param projectId
     * @param knowledgeDB_name
     * @return
     */
    @Override
    public boolean createKnowledgeDB(int projectId, String knowledgeDB_name) {
        Knowledgedb knowledgedb = new Knowledgedb();
        knowledgedb.setProjectId(projectId);
        knowledgedb.setName(knowledgeDB_name);
        knowledgedb.setAbsolutePath(" ");
        return this.save(knowledgedb);
    }

    /**
     * 删除知识库
     *
     * @param projectId
     * @param knowledgeDB
     * @return
     */
    @Override
    public boolean deleteKonwledgeDB(int projectId, String knowledgeDB) {
        // 删除mysql中的知识库
        boolean remove = this.remove(new QueryWrapper<Knowledgedb>().eq("project_id", projectId).eq("name", knowledgeDB));
        if (!remove) {
            log.error("mysql的知识库删除失败");
            return false;
        }

        // 删除mysql中知识库的文件
        boolean knowledge_db_name = fileStorageService.remove(new QueryWrapper<FileStorage>().eq("knowledge_db_name", knowledgeDB));
        if (!knowledge_db_name) {
            log.error("mysql中知识库的没有文件");
        } else{
            // 有文件才删除es里面的数据
            // 构建DeleteByQueryRequest,删除指定索引库里面的文档数据
            DeleteByQueryRequest request = new DeleteByQueryRequest.Builder()
                    .index(String.valueOf(projectId))  // 索引名称
                    .query(Query.of(q -> q
                            .term(t -> t
                                    .field("folder")  // 查询字段
                                    .value(knowledgeDB) // 查询值
                            )
                    ))
                    .build();

            // 执行删除操作
            try {
                DeleteByQueryResponse response = elasticsearchClient.deleteByQuery(request);
            } catch (ElasticsearchException e) {
                // 捕获ElasticsearchException并检查错误消息
                String errorMessage = e.getMessage();
                if (errorMessage.contains("index_not_found_exception")) {
                    log.error("错误：指定的索引库不存在: " + projectId);
                } else {
                    log.error("执行删除操作时发生错误: " + errorMessage);
                }
                return false;
            } catch (IOException e) {
                // 处理其他IO异常
                log.error("执行删除操作时发生IO错误: " + e.getMessage());
                return false;
            }
        }

        //TODO 常规minio里的文件不清除

        return true;
    }



    /**
     * 对OCR结果进行分词后向量化，并存储到es
     * @param text
     * @param indexDocument
     * @return
     */
    @Override
    public boolean addDoc(String text, IndexDocument indexDocument) {
        // 切分文档
        ChineseSentenceSplitter chineseSentenceSplitter = new ChineseSentenceSplitter(200);
        List<String> contents = chineseSentenceSplitter.splitText(text);

        // 向量化
        // TODO 是否按顺序返回
        List<List<Double>> lists = embeddingService.embeddingDocs(contents);

        boolean b = false;

        // 存储到es
        try {
            for (int i = 0; i < lists.size(); i++) {
                List<Double> list = lists.get(i);
                String indexName = String.valueOf(indexDocument.getProjectId());
                String documentId = String.valueOf(i + 1); // 文档 ID 可以根据实际情况生成
                indexDocument.setChunkNumber(documentId);
                indexDocument.setVector(list);
                indexDocument.setPageContent(contents.get(i));

                // 往es里面插入数据
                b = indexService.insertDocument(indexName, documentId, indexDocument);
            }
        } catch (IOException e) {
            log.error("插入es数据错误");
            throw new RuntimeException(e);
        }

        if(b){
            return false;
        }else{
            return true;
        }
    }
}
